package com.core.utils;

import com.core.enums.serializer.DesensitionTypeEnum;
import com.google.common.base.Strings;
import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;

@Slf4j
public final class DesensitizeUtils {
    public static String desensitize(DesensitionTypeEnum type, String value) {
        if (Strings.isNullOrEmpty(value)) {
            return value;
        }

        try {
            switch (type) {

                case PHONE:
                    return overlay(value, repeat(value.length() > 7 ? 4 : value.length() - 3), 3, 7);
                case IDENTITY_NO:
                    return overlay(value, repeat(value.length() > 14 ? 8 : value.length() - 6), 6, 14);
                case CARD_NO:
                    return overlay(value, repeat(value.length() - 8), 4, value.length() - 4);
                case NAME:
                    return Strings.padEnd(left(value, 1), value.length(), '*');
            }
        } catch (Exception e) {
            log.error("数据脱敏异常！", e);
        }
        //TODO:针对不同类型采取不同方式
        return Strings.padStart("", value.length(), '*');
    }


    public static String overlay(String str, String overlay, int start, int end) {
        if (str == null) {
            return null;
        } else {
            if (overlay == null) {
                overlay = "";
            }

            int len = str.length();
            if (start < 0) {
                start = 0;
            }

            if (start > len) {
                start = len;
            }

            if (end < 0) {
                end = 0;
            }

            if (end > len) {
                end = len;
            }

            if (start > end) {
                int temp = start;
                start = end;
                end = temp;
            }

            return str.substring(0, start) + overlay + str.substring(end);
        }
    }

    private static String repeat(int repeat) {
        if (repeat <= 0) {
            return "";
        } else {
            int inputLength = "*".length();
            if (repeat != 1) {
                if (repeat <= 8192) {
                    return padding(repeat, "*".charAt(0));
                } else {
                    int outputLength = inputLength * repeat;
                    int ch0;
                    char ch = "*".charAt(0);
                    char[] output1 = new char[outputLength];

                    for (ch0 = repeat - 1; ch0 >= 0; --ch0) {
                        output1[ch0] = ch;
                    }

                    return new String(output1);

                }
            } else {
                return "*";
            }
        }
    }

    private static String padding(int repeat, char padChar) throws IndexOutOfBoundsException {
        if (repeat < 0) {
            throw new IndexOutOfBoundsException("Cannot pad a negative amount: " + repeat);
        } else {
            char[] buf = new char[repeat];

            Arrays.fill(buf, padChar);

            return new String(buf);
        }
    }

    public static boolean isEmpty(String str) {
        return str == null || str.length() == 0;
    }


    public static String left(String str, int len) {
        if (str == null) {
            return null;
        } else if (len < 0) {
            return "";
        } else {
            return str.length() <= len ? str : str.substring(0, len);
        }
    }

    public static String leftPad(String str, int size, char padChar) {
        if (str == null) {
            return null;
        } else {
            int pads = size - str.length();
            if (pads <= 0) {
                return str;
            } else {
                return pads > 8192 ? leftPad(str, size, String.valueOf(padChar)) : padding(pads, padChar).concat(str);
            }
        }
    }

    public static String leftPad(String str, int size, String padStr) {
        if (str == null) {
            return null;
        } else {
            if (isEmpty(padStr)) {
                padStr = " ";
            }

            int padLen = padStr.length();
            int strLen = str.length();
            int pads = size - strLen;
            if (pads <= 0) {
                return str;
            } else if (padLen == 1 && pads <= 8192) {
                return leftPad(str, size, padStr.charAt(0));
            } else if (pads == padLen) {
                return padStr.concat(str);
            } else if (pads < padLen) {
                return padStr.substring(0, pads).concat(str);
            } else {
                char[] padding = new char[pads];
                char[] padChars = padStr.toCharArray();

                for (int i = 0; i < pads; ++i) {
                    padding[i] = padChars[i % padLen];
                }

                return (new String(padding)).concat(str);
            }
        }
    }

}
